/*
 * Copyright (C) 2015 Actor LLC. <https://actor.im>
 */

package im.actor.core.modules.messaging.history;

import java.util.ArrayList;
import java.util.List;

import im.actor.core.api.ApiDialog;
import im.actor.core.api.ApiMessageState;
import im.actor.core.api.rpc.RequestLoadDialogs;
import im.actor.core.entity.content.AbsContent;
import im.actor.core.modules.api.ApiSupportConfiguration;
import im.actor.core.modules.ModuleContext;
import im.actor.core.modules.messaging.history.entity.DialogHistory;
import im.actor.core.modules.ModuleActor;
import im.actor.runtime.actors.messages.Void;

import static im.actor.core.entity.EntityConverter.convert;

public class DialogsHistoryActor extends ModuleActor {

    // j2objc workaround
    private static final Void DUMB = null;

    private static final int LIMIT = 20;
    private static final String KEY_VERSION = "_1";
    private static final String KEY_LOADED_DATE = "dialogs_history_date" + KEY_VERSION;
    private static final String KEY_LOADED = "dialogs_history_loaded" + KEY_VERSION;
    private static final String KEY_LOADED_INIT = "dialogs_history_inited" + KEY_VERSION;

    private long historyMaxDate;
    private boolean historyLoaded;
    private boolean isLoading = false;

    public DialogsHistoryActor(ModuleContext context) {
        super(context);
    }

    @Override
    public void preStart() {
        historyMaxDate = preferences().getLong(KEY_LOADED_DATE, Long.MAX_VALUE);
        historyLoaded = preferences().getBool(KEY_LOADED, false);
        if (!preferences().getBool(KEY_LOADED_INIT, false)) {
            self().send(new LoadMore());
        } else {
            context().getConductor().getConductor().onDialogsLoaded();
        }
    }

    private void onLoadMore() {
        if (historyLoaded || isLoading) {
            return;
        }
        isLoading = true;

        api(new RequestLoadDialogs(historyMaxDate, LIMIT, ApiSupportConfiguration.OPTIMIZATIONS))
                .chain(r -> updates().loadRequiredPeers(r.getUserPeers(), r.getGroupPeers()))
                .chain(r -> updates().applyRelatedData(r.getUsers(), r.getGroups()))
                .then(r -> onLoadedMore(r.getDialogs()));
    }

    private void onLoadedMore(List<ApiDialog> rawDialogs) {
        final ArrayList<DialogHistory> dialogs = new ArrayList<>();
        long maxLoadedDate = Long.MAX_VALUE;
        for (ApiDialog dialog : rawDialogs) {

            dialogs.add(new DialogHistory(
                    convert(dialog.getPeer()),
                    dialog.getUnreadCount(),
                    dialog.getSortDate(),
                    dialog.getRid(),
                    dialog.getDate(),
                    dialog.getSenderUid(),
                    AbsContent.fromMessage(dialog.getMessage()),
                    dialog.getState() == ApiMessageState.READ,
                    dialog.getState() == ApiMessageState.RECEIVED));

            maxLoadedDate = Math.min(dialog.getSortDate(), maxLoadedDate);
        }

        if (dialogs.size() > 0) {
            final long finalMaxLoadedDate = maxLoadedDate;
            context().getMessagesModule().getRouter().onDialogsHistoryLoaded(dialogs).then((v) -> {
                if (dialogs.size() < LIMIT) {
                    markAsLoaded();
                } else {
                    markAsSliceLoaded(finalMaxLoadedDate);
                }
            });
        } else {
            markAsLoaded();
        }
    }

    private void markAsLoaded() {
        isLoading = false;
        historyLoaded = true;
        preferences().putBool(KEY_LOADED, true);
        preferences().putBool(KEY_LOADED_INIT, true);
        context().getConductor().getConductor().onDialogsLoaded();
    }

    private void markAsSliceLoaded(long date) {
        isLoading = false;
        historyLoaded = false;
        historyMaxDate = date;
        preferences().putBool(KEY_LOADED, false);
        preferences().putBool(KEY_LOADED_INIT, true);
        preferences().putLong(KEY_LOADED_DATE, date);
        context().getConductor().getConductor().onDialogsLoaded();
    }

    //
    // Messages
    //

    @Override
    public void onReceive(Object message) {
        if (message instanceof LoadMore) {
            onLoadMore();
        } else {
            super.onReceive(message);
        }
    }

    public static class LoadMore {

    }
}
